package com.sch.arcgisdemo

import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.animation.Animation
import android.view.animation.RotateAnimation
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
import com.esri.arcgisruntime.data.Geodatabase
import com.esri.arcgisruntime.data.QueryParameters
import com.esri.arcgisruntime.geometry.*
import com.esri.arcgisruntime.layers.*
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.Basemap
import com.esri.arcgisruntime.mapping.view.*
import com.esri.arcgisruntime.symbology.SimpleFillSymbol
import com.esri.arcgisruntime.symbology.SimpleLineSymbol
import com.esri.arcgisruntime.symbology.SimpleMarkerSymbol
import com.sch.arcgisdemo.utils.AssetsUtil.putAssetsToSDCard
import com.sch.arcgisdemo.adapter.LayersListAdapter
import com.sch.arcgisdemo.map.TianDiTuTiledLayerClass
import com.sch.arcgisdemo.utils.PathUtil
import com.yanzhenjie.permission.AndPermission
import com.yanzhenjie.permission.runtime.Permission
import kotlinx.android.synthetic.main.activity_main.*
import java.text.DecimalFormat
import java.text.NumberFormat

class MainActivity : AppCompatActivity() {
    private var locationDisplay: LocationDisplay? = null
    private var popupWindowLayers: PopupWindow? = null
    private val layersAdapter by lazy { LayersListAdapter() }
    private val graphicsOverlay by lazy { GraphicsOverlay() }
    private val queryBoxOverlay by lazy { GraphicsOverlay() }
    private var lastBearing = 0f//指南针最后旋转角度
    private var clickQueryModel = false
    private var boxSelectModel = false
    private var addPointModel = false
    private var addLineModel = false
    private var addAreaModel = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initPermission()
        initMap()
        initListener()
        init()
    }

    private fun init() {
        initPopuWindowLayers()

    }

    private fun initPopuWindowLayers() {
        val view = layoutInflater.inflate(R.layout.popupwindow_layers, null)
        popupWindowLayers = PopupWindow(
            view,
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        )
        val rvLayers = view.findViewById<RecyclerView>(R.id.rvLayers)
        rvLayers.layoutManager = LinearLayoutManager(this)
        rvLayers.adapter = layersAdapter
    }

    private fun initPermission() {
        AndPermission.with(this).runtime()
            .permission(Permission.Group.STORAGE, Permission.Group.LOCATION)
            .onGranted {
                putAssetsToSDCard(
                    this,
                    "well.geodatabase",
                    PathUtil.getLocalGXGeodatabasePath(this)
                )
            }
            .start()
    }

    private fun initMap() {
        //去除水印
        ArcGISRuntimeEnvironment.setLicense("runtimelite,1000,rud4449636536,none,NKMFA0PL4S0DRJE15166")
        //去除logo
        mapView.isAttributionTextVisible = false
        //默认底图
        val webTiledLayer =
            TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                TianDiTuTiledLayerClass.LayerType.TIANDITU_VECTOR_MERCATOR
            )
        //标注
        val webTiledLayerLable =
            TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                TianDiTuTiledLayerClass.LayerType.TIANDITU_VECTOR_MERCATOR_LABLE
            )
        val basemap = Basemap()
        basemap.baseLayers.add(webTiledLayer)
        basemap.baseLayers.add(webTiledLayerLable)
        val arcGISMap = ArcGISMap(basemap)
        mapView.map = arcGISMap
        mapView.graphicsOverlays.add(graphicsOverlay)
        mapView.graphicsOverlays.add(queryBoxOverlay)

        //定位
        locationDisplay = mapView.locationDisplay//获取定位类
        locationDisplay?.isShowLocation = true
        locationDisplay?.isShowPingAnimation = true
        locationDisplay?.isShowAccuracy = true
        locationDisplay?.autoPanMode = LocationDisplay.AutoPanMode.OFF  //设置模式
        locationDisplay?.startAsync()//开始定位

        tvScale.text = "${mapView.mapScale}"
    }

    private val linePoints by lazy { ArrayList<Point>() }
    private val areaPoints by lazy { ArrayList<Point>() }
    private var boxQueryStartPoint: Point? = null
    private var boxQueryEndPoint: Point? = null
    private fun initListener() {
        mapView.addMapScaleChangedListener {
            tvScale.text = "${mapView.mapScale.toInt()}"
        }
        mapView.addMapRotationChangedListener {
            val bearing: Float =
                (360f - mapView.mapRotation).toFloat()
            val rotateAnimation = RotateAnimation(
                lastBearing, bearing, Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f
            )
            rotateAnimation.fillAfter = true
            ivCompass.startAnimation(rotateAnimation)
            lastBearing = bearing
        }
        mapView.onTouchListener = object : DefaultMapViewOnTouchListener(this, mapView) {
            override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
                if (mapView.callout != null && mapView.callout.isShowing) {
                    mapView.callout.dismiss()
                }
                if (addPointModel) {
                    val point =
                        android.graphics.Point(e.x.toInt(), e.y.toInt())
                    val point1: Point = mapView.screenToLocation(point)
                    Log.e("test", point1.toString())
                    // 生成一个红色圆形标识
                    val pointSymbol = SimpleMarkerSymbol(
                        SimpleMarkerSymbol.Style.CIRCLE,
                        Color.RED,
                        10F
                    )
                    val graphic = Graphic(point1, pointSymbol)
                    graphic.attributes["value"] = "graphic：${(Math.random() * 10).toInt()}"
                    graphicsOverlay.graphics.add(graphic)
                } else if (addLineModel) {
                    val point =
                        android.graphics.Point(e.x.toInt(), e.y.toInt())
                    val point1: Point = mapView.screenToLocation(point)
                    linePoints.add(point1)
                    if (linePoints.size == 1) {
                        val pointSymbol = SimpleMarkerSymbol(
                            SimpleMarkerSymbol.Style.SQUARE,
                            Color.BLUE,
                            5F
                        )
                        val graphic = Graphic(point1, pointSymbol)
                        graphicsOverlay.graphics.add(graphic)
                    } else {
                        graphicsOverlay.graphics.clear()
                    }
                    val lineGeometry = PolylineBuilder(mapView.spatialReference)
                    lineGeometry.addPoints(linePoints)
                    val lineSymbol = SimpleLineSymbol(
                        SimpleLineSymbol.Style.SOLID,
                        Color.BLUE,
                        5F
                    )
                    val length = GeometryEngine.length(lineGeometry.toGeometry())
                    val numberFormat = NumberFormat.getInstance()
                    numberFormat.maximumFractionDigits = 2
                    val s = numberFormat.format(length)
                    val lineGraphic = Graphic(lineGeometry.toGeometry(), lineSymbol)
                    lineGraphic.attributes["value"] = "长度：$s 米"
                    graphicsOverlay.graphics.add(lineGraphic)

                } else if (addAreaModel) {
                    val point =
                        android.graphics.Point(e.x.toInt(), e.y.toInt())
                    val point1: Point = mapView.screenToLocation(point)
                    areaPoints.add(point1)
                    if (areaPoints.size == 1) {
                        val pointSymbol = SimpleMarkerSymbol(
                            SimpleMarkerSymbol.Style.SQUARE,
                            Color.argb(128, 255, 255, 0),
                            5F
                        )
                        val graphic = Graphic(point1, pointSymbol)
                        graphicsOverlay.graphics.add(graphic)
                    } else if (areaPoints.size == 2) {
                        val lineGeometry = PolylineBuilder(mapView.spatialReference)
                        lineGeometry.addPoints(areaPoints)
                        val lineSymbol = SimpleLineSymbol(
                            SimpleLineSymbol.Style.SOLID,
                            Color.argb(128, 255, 255, 0),
                            5F
                        )
                        val lineGraphic = Graphic(lineGeometry.toGeometry(), lineSymbol)
                        graphicsOverlay.graphics.add(lineGraphic)
                    } else {
                        graphicsOverlay.graphics.clear()
                    }
                    val polygonGeometry = PolygonBuilder(mapView.spatialReference)
                    polygonGeometry.addPoints(areaPoints)
                    val polygonSymbol = SimpleFillSymbol(
                        SimpleFillSymbol.Style.SOLID,
                        Color.argb(128, 255, 255, 0),
                        null
                    )
                    val area = GeometryEngine.area(polygonGeometry.toGeometry())
                    val numberFormat = NumberFormat.getInstance()
                    numberFormat.maximumFractionDigits = 2
                    val s = numberFormat.format(area)
                    val graphic = Graphic(polygonGeometry.toGeometry(), polygonSymbol)
                    graphic.attributes["value"] = "面积：$s 平方米"
                    graphicsOverlay.graphics.add(graphic)

                } else if (clickQueryModel) {
                    val point =
                        android.graphics.Point(e.x.toInt(), e.y.toInt())
                    queryByPoint(point)

                }
                return super.onSingleTapConfirmed(e)
            }

            override fun onTouch(view: View?, event: MotionEvent?): Boolean {
                if (boxSelectModel) {
                    event?.let {
                        val point =
                            android.graphics.Point(it.x.toInt(), it.y.toInt())
                        if (event.action == MotionEvent.ACTION_DOWN) {
                            boxQueryStartPoint = mapView.screenToLocation(point)
                        }
                        queryBoxOverlay.graphics.clear()
                        boxQueryEndPoint = mapView.screenToLocation(point)
                        if (boxQueryStartPoint != null && boxQueryEndPoint != null) {
                            val envelope = Envelope(
                                boxQueryStartPoint!!.x,
                                boxQueryStartPoint!!.y,
                                boxQueryEndPoint!!.x,
                                boxQueryEndPoint!!.y,
                                mapView.spatialReference
                            )
                            val simpleFillSymbol = SimpleFillSymbol(
                                SimpleFillSymbol.Style.SOLID,
                                Color.argb(128, 255, 255, 0),
                                null
                            )
                            simpleFillSymbol.outline = SimpleLineSymbol(
                                SimpleLineSymbol.Style.DOT,
                                Color.BLUE,
                                1F
                            )
                            val graphic = Graphic(envelope, simpleFillSymbol)
                            queryBoxOverlay.graphics.add(graphic)
                            if (event.action == MotionEvent.ACTION_UP) {
                                queryByEnvelope(envelope)
                            }
                        }
                    }
                    return true
                } else {
                    return super.onTouch(view, event)
                }
            }
        }
        locationDisplay?.addLocationChangedListener {
            val mapPoint = locationDisplay?.mapLocation
            mapPoint?.let {
                tvMapWkid.text = "地图坐标：(wkid:${mapPoint.spatialReference.wkid})"
                tvMapLocationX.text = "X：${it.x}"
                tvMapLocationY.text = "Y：${it.y}"
                val wgs84Point: Point =
                    GeometryEngine.project(it, SpatialReference.create(4326)) as Point
                tvWgs84LocationX.text =
                    "经度(X)：" + DecimalFormat("##########.##########").format(wgs84Point.x)
                tvWgs84LocationY.text =
                    "纬度(Y)：" + DecimalFormat("##########.##########").format(wgs84Point.y)
            }
            val wgs84Point = locationDisplay?.location?.position  //直接得到的wgs84坐标系
            wgs84Point?.let {
                tvGetWgs84LocationX.text = "经度(X)：${it.x}"
                tvGetWgs84LocationY.text = "纬度(Y)：${it.y}"
            }
        }
        fab_map_tianditu.setOnClickListener {
            rgMapType.visibility = View.VISIBLE
            //默认底图
            val webTiledLayer =
                TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                    TianDiTuTiledLayerClass.LayerType.TIANDITU_VECTOR_MERCATOR
                )
            //标注
            val webTiledLayerLable =
                TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                    TianDiTuTiledLayerClass.LayerType.TIANDITU_VECTOR_MERCATOR_LABLE
                )
            val basemap = Basemap()
            basemap.baseLayers.add(webTiledLayer)
            basemap.baseLayers.add(webTiledLayerLable)
            val arcGISMap = ArcGISMap(basemap)
            mapView.map = arcGISMap
            fam_map.close(false)
            clearModel()
            clearMap()
        }
        fab_map0.setOnClickListener {
            rgMapType.visibility = View.GONE
            val url =
                "http://36.35.240.240:9090/REST/System/TENANTBASE/spatial/V1.0/SpatialService/2DTileService/CZMAP/Directory/CZMAP4509/2019/DEFAULT/ArcGIS";
            val arcGISTiledLayer = ArcGISTiledLayer(url)
            val arcGISMap = ArcGISMap(Basemap(arcGISTiledLayer))
            mapView.map = arcGISMap
            fam_map.close(false)
            clearModel()
            clearMap()
        }
        fab_map1.setOnClickListener {
            rgMapType.visibility = View.GONE
            val url =
                "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer";
            val arcGISTiledLayer = ArcGISTiledLayer(url)
            val arcGISMap = ArcGISMap(Basemap(arcGISTiledLayer))
            mapView.map = arcGISMap
            fam_map.close(false)
            clearModel()
            clearMap()
        }
        fab_map2.setOnClickListener {
            rgMapType.visibility = View.GONE
            val url =
                "http://www.arcgis.com/home/webmap/viewer.html?webmap=55c1665bcd064552944a9e8296271ec3";
            val arcGISMap = ArcGISMap(url)
            mapView.map = arcGISMap
            fam_map.close(false)
            clearModel()
            clearMap()
        }
        fab_map3.setOnClickListener {
            rgMapType.visibility = View.GONE
            val url =
                "https://basemaps.arcgis.com/v1/arcgis/rest/services/World_Basemap/VectorTileServer";
            val arcGISVectorTiledLayer = ArcGISVectorTiledLayer(url);
            val arcGISMap = ArcGISMap(Basemap(arcGISVectorTiledLayer))
            mapView.map = arcGISMap
            fam_map.close(false)
            clearModel()
            clearMap()
        }
        fab_center.setOnClickListener {
            mapView.setViewpointCenterAsync(Point(1.2957313863797672E7, 4852689.604022887), 50000.0)
            fam_location.close(false)
        }
        fab_my_location.setOnClickListener {
            if (locationDisplay?.autoPanMode == LocationDisplay.AutoPanMode.OFF) {
                locationDisplay?.autoPanMode = LocationDisplay.AutoPanMode.COMPASS_NAVIGATION
            } else {
                mapView.setViewpointRotationAsync(0.0)
                locationDisplay?.autoPanMode = LocationDisplay.AutoPanMode.OFF

            }
            fam_location.close(false)

        }
        fab_envelope.setOnClickListener {
            val envelope = Envelope(
                1.2948833926058898E7,
                4349896.492981933,
                1.3109843192109745E7,
                4447340.642539789,
                mapView.spatialReference
            )
            mapView.setViewpointGeometryAsync(envelope)
            fam_location.close(false)

        }
        fab_addPoint.setOnClickListener {
            clearModel()
            tvModel.text = "添加点模式"
            addPointModel = true
            clearMap()
            fam_add.close(false)

        }
        fab_addLine.setOnClickListener {
            clearModel()
            tvModel.text = "添加线模式"
            addLineModel = true
            clearMap()
            fam_add.close(false)

        }
        fab_addArea.setOnClickListener {
            clearModel()
            tvModel.text = "添加面模式"
            addAreaModel = true
            clearMap()
            fam_add.close(false)

        }
        fab_addGeodatabase.setOnClickListener {
            var path =
                "${PathUtil.getLocalGXGeodatabasePath(this)}/well.geodatabase"
            val geodatabase = Geodatabase(path)
            geodatabase.loadAsync()
            geodatabase.addDoneLoadingListener {
                val wellFeatureLayers = ArrayList<FeatureLayer>()
                for (geoFeatureTable in geodatabase.geodatabaseFeatureTables) {
                    val featureLayer = FeatureLayer(geoFeatureTable)
                    wellFeatureLayers.add(featureLayer)
                }
                mapView.map.operationalLayers.addAll(wellFeatureLayers)
                mapView.setViewpointCenterAsync(
                    Point(13169482.189464, 3802566.889675), 9000.0
                )
            }
            fam_add.close(false)

        }
        fab_clickQuery.setOnClickListener {
            clearModel()
            mapView.callout.dismiss()
            tvModel.text = "单击查询模式"
            clickQueryModel = true
            fam_query.close(false)
        }
        fab_boxSelect.setOnClickListener {
            if (mapView.map.operationalLayers.size > 0) {
                clearModel()
                mapView.callout.dismiss()
                tvModel.text = "拉框查询模式"
                boxSelectModel = true
                fam_query.close(false)
            } else {
                Toast.makeText(this, "暂无业务图层", Toast.LENGTH_SHORT).show()
            }
        }
        ivCompass.setOnClickListener {
            mapView.setViewpointRotationAsync(0.0)
            mapView.setViewpointScaleAsync(mapView.mapScale * 2)
        }
        ivLayerManager.setOnClickListener {
            val layers = ArrayList<Layer>()
            mapView.map.operationalLayers.forEach {
                layers.add(it)
            }
            if (layers.size > 0) {
                layersAdapter.updata(layers)
                popupWindowLayers?.let {
                    if (it.isShowing) {
                        it.dismiss()
                    } else {
                        it.showAsDropDown(ivLayerManager, -155, -50)
                    }
                }
            } else {
                Toast.makeText(this, "暂无业务图层", Toast.LENGTH_SHORT).show()
            }

        }
        ivClera.setOnClickListener {
            clearModel()
            clearMap()
        }
        rgMapType.setOnCheckedChangeListener { radioGroup, i ->
            when (i) {
                R.id.rbVec -> {
                    //默认底图
                    val webTiledLayer =
                        TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                            TianDiTuTiledLayerClass.LayerType.TIANDITU_VECTOR_MERCATOR
                        )
                    //标注
                    val webTiledLayerLable =
                        TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                            TianDiTuTiledLayerClass.LayerType.TIANDITU_VECTOR_MERCATOR_LABLE
                        )
                    val basemap = Basemap()
                    basemap.baseLayers.add(webTiledLayer)
                    basemap.baseLayers.add(webTiledLayerLable)
                    val arcGISMap = ArcGISMap(basemap)
                    mapView.map = arcGISMap
                }
                R.id.rbImg -> {
                    val webTiledLayer =
                        TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                            TianDiTuTiledLayerClass.LayerType.TIANDITU_IMAGE_MERCATOR
                        )
                    val webTiledLayerLable =
                        TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                            TianDiTuTiledLayerClass.LayerType.TIANDITU_IMAGE_MERCATOR_LABLE
                        )
                    val basemap = Basemap()
                    basemap.baseLayers.add(webTiledLayer)
                    basemap.baseLayers.add(webTiledLayerLable)
                    val arcGISMap = ArcGISMap(basemap)
                    mapView.map = arcGISMap
                }
                R.id.rbTer -> {
                    val webTiledLayer =
                        TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                            TianDiTuTiledLayerClass.LayerType.TIANDITU_TERRAIN_MERCATOR
                        )
                    val webTiledLayerLable =
                        TianDiTuTiledLayerClass.CreateTianDiTuTiledLayer(
                            TianDiTuTiledLayerClass.LayerType.TIANDITU_TERRAIN_MERCATOR_LABLE
                        )
                    val basemap = Basemap()
                    basemap.baseLayers.add(webTiledLayer)
                    basemap.baseLayers.add(webTiledLayerLable)
                    val arcGISMap = ArcGISMap(basemap)
                    mapView.map = arcGISMap
                }
            }

        }
    }

    private fun queryByPoint(point: android.graphics.Point) {
        val operationalLayers = mapView.map.operationalLayers
        if (operationalLayers != null && operationalLayers.size > 0) {
            val listListenableFuture = mapView.identifyLayerAsync(
                operationalLayers[operationalLayers.lastIndex],
                point,
                15.0,
                false,
                -1
            )
            listListenableFuture.addDoneListener {
                val elements = listListenableFuture.get().elements
                for (element in elements) {
                    Log.e("test", element.attributes.keys.toString())
                    Log.e("test", element.attributes.values.toString())
                    if (element.attributes.containsKey("heignth")) {
                        showCallout(
                            "名称：${element.attributes["stationnam"]} \n" +
                                    "降雨量：${element.attributes["heignth"]}mm \n" +
                                    "时间：${element.attributes["data_year"]}年 ${element.attributes["data_month"]}月",
                            element.geometry.extent.center
                        )
                    } else if (element.attributes.containsKey("安装位")) {
                        showCallout(
                            "位置：${element.attributes["安装位"]} \n" +
                                    "材质：${element.attributes["井盖材"]} \n" +
                                    "类型：${element.attributes["井盖类"]}",
                            element.geometry.extent.center
                        )
                    }

                }
            }
        }
        val listListenableFuture = mapView.identifyGraphicsOverlayAsync(
            mapView.graphicsOverlays[0],
            point,
            15.0,
            false
        )
        listListenableFuture.addDoneListener {
            val graphics = listListenableFuture.get().graphics
            for (graphic in graphics) {
                graphic.isSelected = true
                showCallout(
                    graphic.attributes["value"].toString(),
                    graphic.geometry.extent.center
                )
            }
        }
    }

    private fun queryByEnvelope(envelope: Envelope) {
        val operationalLayers = mapView.map.operationalLayers
        if (operationalLayers != null && operationalLayers.size > 0) {
            val queryParameters = QueryParameters()
            queryParameters.geometry = envelope
            val dataFeatureLayer: FeatureLayer = operationalLayers[0] as FeatureLayer
            val mTable = dataFeatureLayer.featureTable
            val featureQueryResult = mTable.queryFeaturesAsync(queryParameters)
            featureQueryResult.addDoneListener {
                val featureResult = featureQueryResult.get()
                Toast.makeText(this, "查询到${featureResult.toList().size} 个元素", Toast.LENGTH_LONG)
                    .show()
                for (element in featureResult) {
                    Log.e("test", "${element.attributes.keys}")
                }
            }
        }
    }

    fun clearModel() {
        tvModel.text = ""
        addPointModel = false
        addLineModel = false
        addAreaModel = false
        clickQueryModel = false
        boxSelectModel = false
    }

    fun clearMap() {
        linePoints.clear()
        areaPoints.clear()
        graphicsOverlay.graphics.clear()
        queryBoxOverlay.graphics.clear()
        mapView.callout.dismiss()
    }

    fun showCallout(value: String, point: Point) {
        val view = View.inflate(this, R.layout.callout, null)
        val tvValue = view.findViewById<TextView>(R.id.tvValue)
        tvValue.text = value
        mapView.callout.show(view, point)
        val  callout = mapView.callout

        //设置Callout样式
        val style =  Callout.Style(this);
        style.maxWidth = 400; //设置最大宽度
        style.maxHeight = 300;  //设置最大高度
        style.minWidth = 200;  //设置最小宽度
        style.minHeight = 100;  //设置最小高度
        style.borderWidth = 2; //设置边框宽度
        style.borderColor = Color.BLUE; //设置边框颜色
        style.backgroundColor = Color.WHITE; //设置背景颜色
        style.cornerRadius = 8; //设置圆角半径
        style.leaderPosition = Callout.Style.LeaderPosition.LOWER_MIDDLE; //设置指示性位置

    }
}